home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 37 / IOPROG_37.ISO / SOFT / Multilizer.exe / disk1 / data1.cab / data1 / [Group9]VCL Source Standard / ivconnection.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-12  |  23.8 KB  |  1,140 lines

  1. unit IvConnection;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes;
  7.  
  8. type
  9.   TIvConnection = class;
  10.   TIvStatement = class;
  11.   TIvResultSet = class;
  12.  
  13.   TIvTransactionSupport = (ivtsNone, ivtsDML, ivtsAll, ivtsCommit, ivtsIgnore);
  14.  
  15.   // Connection
  16.  
  17.   TIvDataSourceInfo = class(TObject)
  18.   private
  19.     FServerName: String;
  20.     FDescriction: String;
  21.  
  22.   public
  23.     constructor Create(serverName: String; description: String);
  24.  
  25.     property ServerName: String read FServerName;
  26.     property Descriction: String read FDescriction;
  27.   end;
  28.  
  29.  
  30.   TIvTableInfo = class(TObject)
  31.   private
  32.     FTableName: String;
  33.     FDescriction: String;
  34.  
  35.   public
  36.     constructor Create(tableName: String; description: String);
  37.  
  38.     property TableName: String read FTableName;
  39.     property Descriction: String read FDescriction;
  40.   end;
  41.  
  42.  
  43.   TIvEnvironment = class(TObject)
  44.   private
  45.     FConnections: TList;
  46.     FDataSources: TList;
  47.     FHandle: Pointer;
  48.  
  49.     constructor Create;
  50.  
  51.     function GetConnectionCount: Integer;
  52.     function GetConnections(index: Integer): TIvConnection;
  53.     function GetDataSourceCount: Integer;
  54.     function GetDataSources(index: Integer): TIvDataSourceInfo;
  55.  
  56.     procedure AddConnection(item: TIvConnection);
  57.     procedure RemoveConnection(item: TIvConnection);
  58.  
  59.     procedure ClearDataSources;
  60.  
  61.   public
  62.     destructor Destroy; override;
  63.  
  64.     function ConnectionByName(name: String): TIvConnection;
  65.  
  66.     property ConnectionCount: Integer read GetConnectionCount;
  67.     property Connections[index: Integer]: TIvConnection read GetConnections;
  68.     property DataSourceCount: Integer read GetDataSourceCount;
  69.     property DataSources[index: Integer]: TIvDataSourceInfo read GetDataSources;
  70.     property Handle: Pointer read FHandle;
  71.   end;
  72.  
  73.  
  74.   TIvConnection = class(TObject)
  75.   private
  76.     FAutoCommit: Boolean;
  77.     FHandle: Pointer;
  78.     FConnectionName: String;
  79.     FDataSource: String;
  80.     FPassword: String;
  81.     FUsername: String;
  82.  
  83.     function GetActive: Boolean;
  84.  
  85.     procedure SetActive(value: Boolean);
  86.     procedure SetAutoCommit(value: Boolean);
  87.     procedure SetConnectionName(value: String);
  88.  
  89.     procedure HandleReturn(code: Integer);
  90.  
  91.   public
  92.     constructor Create; virtual;
  93.     destructor Destroy; override;
  94.  
  95.     function CreateStatement: TIvStatement;
  96.     function CreateResultSet: TIvResultSet;
  97.  
  98.     function SelectTables: TIvResultSet;
  99.  
  100.     function GetTransactionSupport: TIvTransactionSupport;
  101.  
  102.     procedure Open;
  103.     procedure Close;
  104.     procedure Execute(const sql: String);
  105.  
  106.     procedure Commit;
  107.     procedure Rollback;
  108.  
  109.     property Active: Boolean read GetActive write SetActive;
  110.     property AutoCommit: Boolean read FAutoCommit write SetAutoCommit;
  111.     property ConnectionName: String read FConnectionName write SetConnectionName;
  112.     property DataSource: String read FDataSource write FDataSource;
  113.     property Handle: Pointer read FHandle;
  114.     property Password: String read FPassword write FPassword;
  115.     property Username: String read FUsername write FUsername;
  116.   end;
  117.  
  118.  
  119.   // Statement
  120.  
  121.   TIvParameter = class(TObject)
  122.   private
  123.     FOwner: TIvStatement;
  124.     FIndex: Integer;
  125.     FCType: Integer;
  126.     FSqlType: Smallint;
  127.     FColDef: Longint;
  128.     FScale: Smallint;
  129.     FNullable: Smallint;
  130.     FBuffer: Pointer;
  131.     FBufferSize: Integer;
  132.  
  133.     function GetNumber: Integer;
  134.  
  135.     procedure SetAsBoolean(value: Boolean);
  136.     procedure SetAsCurrency(value: Currency);
  137.     procedure SetAsDate(value: TDateTime);
  138.     procedure SetAsDateTime(value: TDateTime);
  139.     procedure SetAsFloat(value: Double);
  140.     procedure SetAsInteger(value: Integer);
  141.     procedure SetAsStream(value: TStream);
  142.     procedure SetAsString(value: String);
  143.     procedure SetAsTime(value: TDateTime);
  144.  
  145.     procedure SetData(cType: Integer; const buffer; bufferSize: Integer);
  146.  
  147.     constructor Create(owner: TIvStatement; index: Integer);
  148.  
  149.     property Number: Integer read GetNumber;
  150.  
  151.   public
  152.     destructor Destroy; override;
  153.  
  154.     procedure SetNull;
  155.  
  156.     property AsBoolean: Boolean write SetAsBoolean;
  157.     property AsDate: TDateTime write SetAsDate;
  158.     property AsDateTime: TDateTime write SetAsDateTime;
  159.     property AsCurrency: Currency write SetAsCurrency;
  160.     property AsFloat: Double write SetAsFloat;
  161.     property AsInteger: Integer write SetAsInteger;
  162.     property AsStream: TStream write SetAsStream;
  163.     property AsString: String write SetAsString;
  164.     property AsTime: TDateTime write SetAsTime;
  165.   end;
  166.  
  167.  
  168.   TIvStatement = class(TObject)
  169.   private
  170.     FConnection: TIvConnection;
  171.     FHandle: Pointer;
  172.     FParameters: TList;
  173.  
  174.     function GetParameterCount: Integer;
  175.     function GetParameters(index: Integer): TIvParameter;
  176.  
  177.     procedure LoadParameters;
  178.     procedure ClearParameters;
  179.  
  180.     procedure HandleReturn(code: Integer);
  181.  
  182.   protected
  183.     constructor Create(connection: TIvConnection); virtual;
  184.  
  185.   public
  186.     destructor Destroy; override;
  187.  
  188.     procedure ExecuteDirect(const sql: String); virtual;
  189.     procedure Prepare(const sql: String); virtual;
  190.     procedure Execute; virtual;
  191.     procedure Close; virtual;
  192.  
  193.     procedure InitParameters;
  194.  
  195.     property Handle: Pointer read FHandle;
  196.     property ParameterCount: Integer read GetParameterCount;
  197.     property Parameters[index: Integer]: TIvParameter read GetParameters;
  198.   end;
  199.  
  200.  
  201.   // Resultset
  202.  
  203.   TIvColumn = class(TObject)
  204.   private
  205.     FOwner: TIvResultSet;
  206.     FIndex: Integer;
  207.     FName: String;
  208.     FDataType: Smallint;
  209.     FSize: Integer;
  210.     FDecimalDigits: Smallint;
  211.     FNullable: Smallint;
  212.     FWasNull: Boolean;
  213.  
  214.     function GetAsBoolean: Boolean;
  215.     function GetAsDate: TDateTime;
  216.     function GetAsDateTime: TDateTime;
  217.     function GetAsCurrency: Currency;
  218.     function GetAsFloat: Double;
  219.     function GetAsInteger: Integer;
  220.     function GetAsStream: TMemoryStream;
  221.     function GetAsString: String;
  222.     function GetAsTime: TDateTime;
  223.     function GetIsBlob: Boolean;
  224.     function GetNumber: Integer;
  225.  
  226.     function GetData(
  227.       targetType: Smallint;
  228.       var buffer;
  229.       bufferLength: Integer;
  230.       var indicator: Integer): Integer;
  231.  
  232.     constructor Create(owner: TIvResultSet; index: Integer);
  233.  
  234.     property Number: Integer read GetNumber;
  235.  
  236.   public
  237.     destructor Destroy; override;
  238.  
  239.     property AsBoolean: Boolean read GetAsBoolean;
  240.     property AsDate: TDateTime read GetAsDate;
  241.     property AsDateTime: TDateTime read GetAsDateTime;
  242.     property AsCurrency: Currency read GetAsCurrency;
  243.     property AsFloat: Double read GetAsFloat;
  244.     property AsInteger: Integer read GetAsInteger;
  245.     property AsStream: TMemoryStream read GetAsStream;
  246.     property AsString: String read GetAsString;
  247.     property AsTime: TDateTime read GetAsTime;
  248.     property IsBlob: Boolean read GetIsBlob;
  249.     property DataType: Smallint read FDataType;
  250.     property Name: String read FName;
  251.     property Size: Integer read FSize;
  252.     property WasNull: Boolean read FWasNull;
  253.   end;
  254.  
  255.  
  256.   TIvResultSet = class(TIvStatement)
  257.   private
  258.     FColumns: TList;
  259.     FEOF: Boolean;
  260.  
  261.     function GetColumnCount: Integer;
  262.     function GetColumns(index: Integer): TIvColumn;
  263.  
  264.     procedure LoadColumns;
  265.     procedure ClearColumns;
  266.  
  267.   protected
  268.     constructor Create(connection: TIvConnection); override;
  269.  
  270.   public
  271.     destructor Destroy; override;
  272.  
  273.     function ColumnByName(const name: String): TIvColumn;
  274.  
  275.     procedure ExecuteDirect(const sql: String); override;
  276.     procedure ExecuteDirectFast(const sql: String);
  277.     procedure Prepare(const sql: String); override;
  278.     procedure Execute; override;
  279.  
  280.     function Next: boolean;
  281.  
  282.     property EOF: Boolean read FEOF;
  283.     property ColumnCount: Integer read GetColumnCount;
  284.     property Columns[index: Integer]: TIvColumn read GetColumns;
  285.   end;
  286.  
  287. var
  288.   IvEnvironment: TIvEnvironment;
  289.  
  290. implementation
  291.  
  292. uses
  293.   SysUtils,
  294.   Dialogs,
  295.   Windows,
  296.   ODBC;
  297.  
  298.  
  299. procedure HandleError(
  300.   code: Integer;
  301.   environment: Pointer;
  302.   connection: Pointer;
  303.   statement: Pointer);
  304. var
  305.   native: Integer;
  306.   outLen: Integer;
  307.   buffer1: array[0..15] of Char;
  308.   buffer2: array[0..255] of Char;
  309. begin
  310.   if (code <> SQL_SUCCESS) and (code <> SQL_SUCCESS_WITH_INFO) then
  311.   begin
  312.     SQLError(environment, connection, statement, buffer1, native, buffer2, 255, outlen);
  313.     raise Exception.Create(StrPas(buffer2));
  314.   end;
  315. end;
  316.  
  317.  
  318. { TIvDataSourceInfo }
  319.  
  320. constructor TIvDataSourceInfo.Create(serverName: String; description: String);
  321. begin
  322.   FServerName := serverName;
  323.   FDescriction := description;
  324. end;
  325.  
  326.  
  327. { TIvTableInfo }
  328.  
  329. constructor TIvTableInfo.Create(tableName: String; description: String);
  330. begin
  331.   FTableName := tableName;
  332.   FDescriction := description;
  333. end;
  334.  
  335.  
  336. { TIvEnvironment }
  337.  
  338. constructor TIvEnvironment.Create;
  339. var
  340.   code: Integer;
  341.   length1: Smallint;
  342.   length2: Smallint;
  343.   buffer1: array[0..255] of Char;
  344.   buffer2: array[0..255] of Char;
  345. begin
  346.   inherited Create;
  347.   FConnections := TList.Create;
  348.   FDataSources := TList.Create;
  349.  
  350.   SQLAllocEnv(FHandle);
  351.  
  352.   code := SQLDataSources(
  353.     FHandle,
  354.     SQL_FETCH_FIRST,
  355.     buffer1,
  356.     SizeOf(buffer1),
  357.     length1,
  358.     buffer2,
  359.     SizeOf(buffer2),
  360.     length2);
  361.  
  362.   while code = SQL_SUCCESS do
  363.   begin
  364.     FDataSources.Add(TIvDataSourceInfo.Create(StrPas(buffer1), StrPas(buffer2)));
  365.  
  366.     code := SQLDataSources(
  367.       FHandle,
  368.       SQL_FETCH_NEXT,
  369.       buffer1,
  370.       SizeOf(buffer1),
  371.       length1,
  372.       buffer2,
  373.       SizeOf(buffer2),
  374.       length2);
  375.   end;
  376. end;
  377.  
  378. destructor TIvEnvironment.Destroy;
  379. begin
  380.   SqlFreeEnv(FHandle);
  381.   ClearDataSources;
  382.   FDataSources.Free;
  383.   inherited Destroy;
  384. end;
  385.  
  386. procedure TIvEnvironment.ClearDataSources;
  387. var
  388.   i: Integer;
  389. begin
  390.   for i := 0 to DataSourceCount - 1 do
  391.     DataSources[i].Free;
  392.  
  393.   FDataSources.Clear;
  394. end;
  395.  
  396. function TIvEnvironment.GetConnectionCount: Integer;
  397. begin
  398.   Result := FConnections.Count;
  399. end;
  400.  
  401. function TIvEnvironment.GetConnections(index: Integer): TIvConnection;
  402. begin
  403.   Result := FConnections[index];
  404. end;
  405.  
  406. function TIvEnvironment.GetDataSourceCount: Integer;
  407. begin
  408.   Result := FDataSources.Count;
  409. end;
  410.  
  411. function TIvEnvironment.GetDataSources(index: Integer): TIvDataSourceInfo;
  412. begin
  413.   Result := FDataSources[index];
  414. end;
  415.  
  416. procedure TIvEnvironment.AddConnection(item: TIvConnection);
  417. begin
  418.   FConnections.Add(item);
  419. end;
  420.  
  421. procedure TIvEnvironment.RemoveConnection(item: TIvConnection);
  422. begin
  423.   FConnections.Remove(item);
  424. end;
  425.  
  426. function TIvEnvironment.ConnectionByName(name: String): TIvConnection;
  427. var
  428.   i: Integer;
  429. begin
  430.   for i := 0 to ConnectionCount - 1 do
  431.   begin
  432.     Result := Connections[i];
  433.  
  434.     if Result.ConnectionName = name then
  435.       Exit;
  436.   end;
  437.  
  438.   Result := nil;
  439. end;
  440.  
  441.  
  442. { TIvConnection }
  443.  
  444. constructor TIvConnection.Create;
  445. begin
  446.   inherited Create;
  447.   IvEnvironment.AddConnection(Self);
  448.   FAutoCommit := True;
  449. end;
  450.  
  451. destructor TIvConnection.Destroy;
  452. begin
  453.   IvEnvironment.RemoveConnection(Self);
  454.   Close;
  455.   inherited Destroy;
  456. end;
  457.  
  458. function TIvConnection.GetTransactionSupport: TIvTransactionSupport;
  459. var
  460.   len: Word;
  461.   value, code: Integer;
  462. begin
  463.   value := Word(ivtsNone);
  464.   code := SQLGetInfo(FHandle, SQL_TXN_CAPABLE, @value, Sizeof(value), len);
  465.   HandleReturn(code);
  466.   Result := TIvTransactionSupport(value);
  467. end;
  468.  
  469. function TIvConnection.GetActive: Boolean;
  470. begin
  471.   Result := (FHandle <> nil);
  472. end;
  473.  
  474. procedure TIvConnection.SetActive(value: Boolean);
  475. var
  476.   code: Integer;
  477. begin
  478.   if Active <> value then
  479.   begin
  480.     if value then
  481.     begin
  482.       SQLAllocConnect(IvEnvironment.Handle, FHandle);
  483.  
  484.       code := SQLConnect(
  485.         FHandle,
  486.         PChar(FDataSource),
  487.         Length(FDataSource),
  488.         PChar(FUsername),
  489.         Length(FUsername),
  490.         PChar(FPassword),
  491.         Length(FPassword));
  492.  
  493.       HandleReturn(code);
  494.     end
  495.     else
  496.     begin
  497.       SqlFreeConnect(FHandle);
  498.       FHandle := nil;
  499.     end;
  500.   end;
  501. end;
  502.  
  503. procedure TIvConnection.SetAutoCommit(value: Boolean);
  504. var
  505.   param: Longint;
  506.   code: Integer;
  507. begin
  508.   if FAutoCommit <> value then
  509.   begin
  510.     if value then
  511.       param := SQL_AUTOCOMMIT_ON
  512.     else
  513.       param := SQL_AUTOCOMMIT_OFF;
  514.  
  515.     code := SQLSetConnectOption(FHandle, SQL_AUTOCOMMIT, param);
  516.     HandleReturn(code);
  517.     FAutoCommit := value;
  518.   end;
  519. end;
  520.  
  521. procedure TIvConnection.SetConnectionName(value: String);
  522. begin
  523.   FConnectionName := value;
  524. end;
  525.  
  526. function TIvConnection.CreateStatement: TIvStatement;
  527. begin
  528.   Result := TIvStatement.Create(Self);
  529. end;
  530.  
  531. function TIvConnection.CreateResultSet: TIvResultSet;
  532. begin
  533.   Result := TIvResultSet.Create(Self);
  534. end;
  535.  
  536. procedure TIvConnection.Execute(const sql: String);
  537. var
  538.   statement: TIvStatement;
  539. begin
  540.   statement := CreateStatement;
  541.   statement.ExecuteDirect(sql);
  542.   statement.Free;
  543. end;
  544.  
  545. function TIvConnection.SelectTables: TIvResultSet;
  546. var
  547.   code: Integer;
  548. begin
  549.   Result := CreateResultSet;
  550.  
  551.   code := SQLTables(
  552.     Result.Handle,
  553.     nil,
  554.     0,
  555.     nil, //PChar(FUsername),
  556.     0, //Length(FUsername),
  557.     nil,
  558.     0,
  559.     nil,
  560.     0);
  561.  
  562.   Result.HandleReturn(code);
  563.  
  564.   Result.LoadColumns;
  565. end;
  566.  
  567. procedure TIvConnection.Open;
  568. begin
  569.   Active := True;
  570. end;
  571.  
  572. procedure TIvConnection.Close;
  573. begin
  574.   Active := False;
  575. end;
  576.  
  577. procedure TIvConnection.Commit;
  578. var
  579.   code: Integer;
  580. begin
  581.   code := SQLTransact(IvEnvironment.Handle, FHandle, SQL_COMMIT);
  582.   HandleReturn(code);
  583. end;
  584.  
  585. procedure TIvConnection.Rollback;
  586. var
  587.   code: Integer;
  588. begin
  589.   code := SQLTransact(IvEnvironment.Handle, FHandle, SQL_ROLLBACK);
  590.   HandleReturn(code);
  591. end;
  592.  
  593. procedure TIvConnection.HandleReturn(code: Integer);
  594. begin
  595.   HandleError(code, IvEnvironment.Handle, FHandle, nil);
  596. end;
  597.  
  598.  
  599. { TIvParameter }
  600.  
  601. constructor TIvParameter.Create(
  602.   owner: TIvStatement;
  603.   index: Integer);
  604. begin
  605.   inherited Create;
  606.   FOwner := owner;
  607.   FIndex := index;
  608. end;
  609.  
  610. destructor TIvParameter.Destroy;
  611. begin
  612.   FreeMem(FBuffer);
  613.   inherited Destroy;
  614. end;
  615.  
  616. function TIvParameter.GetNumber: Integer;
  617. begin
  618.   Result := FIndex + 1;
  619. end;
  620.  
  621. procedure TIvParameter.SetData(
  622.   cType: Integer;
  623.   const buffer;
  624.   bufferSize: Integer);
  625. var
  626.   code: Integer;
  627. begin
  628.   FCType := cType;
  629.  
  630.   code := SQLDescribeParam(
  631.     FOwner.Handle,
  632.     Number,
  633.     FSqlType,
  634.     FColDef,
  635.     FScale,
  636.     FNullable);
  637.  
  638.   FOwner.HandleReturn(code);
  639.  
  640.   FBufferSize := bufferSize;
  641.   GetMem(FBuffer, FBufferSize);
  642.   Move(buffer, FBuffer^, bufferSize);
  643.  
  644.   if FBufferSize = 0 then
  645.     FBufferSize := SQL_NULL_DATA;
  646.  
  647.   if FCType = SQL_C_CHAR then
  648.     FBufferSize := SQL_NTS;
  649.  
  650.   code := SQLBindParameter(
  651.     FOwner.Handle,
  652.     Number,
  653.     SQL_PARAM_INPUT,
  654.     FCType,
  655.     FSqlType,
  656.     FColDef,
  657.     FScale,
  658.     FBuffer,
  659.     0,
  660.     FBufferSize);
  661.  
  662.   FOwner.HandleReturn(code);
  663. end;
  664.  
  665. procedure TIvParameter.SetAsStream(value: TStream);
  666. var
  667.   tmp: TMemoryStream;
  668. begin
  669.   tmp := TMemoryStream.Create;
  670.   tmp.LoadFromStream(value);
  671.  
  672.   SetData(SQL_C_BINARY, tmp.Memory^, tmp.Size);
  673.  
  674.   tmp.Free;
  675. end;
  676.  
  677. procedure TIvParameter.SetAsBoolean(value: Boolean);
  678. begin
  679.   SetData(SQL_C_BIT, value, SizeOf(value));
  680. end;
  681.  
  682. procedure TIvParameter.SetAsCurrency(value: Currency);
  683. var
  684.   tmp: Double;
  685. begin
  686.   tmp := value;
  687.   SetData(SQL_C_DOUBLE, tmp, SizeOf(tmp));
  688. end;
  689.  
  690. procedure TIvParameter.SetAsDate(value: TDateTime);
  691. var
  692.   tmp: TOdbcDateStruct;
  693. begin
  694.   DecodeDate(value, tmp.year, tmp.month, tmp.day);
  695.   SetData(SQL_C_DATE, tmp, SizeOf(tmp));
  696. end;
  697.  
  698. procedure TIvParameter.SetAsFloat(value: Double);
  699. begin
  700.   SetData(SQL_C_DOUBLE, value, SizeOf(value));
  701. end;
  702.  
  703. procedure TIvParameter.SetAsInteger(value: Integer);
  704. begin
  705.   SetData(SQL_C_SLONG, value, SizeOf(value));
  706. end;
  707.  
  708. procedure TIvParameter.SetAsString(value: String);
  709. begin
  710.   SetData(SQL_C_CHAR, PChar(value)^, Length(value) + 1);
  711. end;
  712.  
  713. procedure TIvParameter.SetAsTime(value: TDateTime);
  714. var
  715.   tmp: TOdbcTimeStruct;
  716.   fraction: Word;
  717. begin
  718.   DecodeTime(value, tmp.hour, tmp.minute, tmp.second, fraction);
  719.   SetData(SQL_C_TIME, tmp, SizeOf(tmp));
  720. end;
  721.  
  722. procedure TIvParameter.SetAsDateTime(value: TDateTime);
  723. var
  724.   tmp: TOdbcTimestampStruct;
  725.   fraction: Word;
  726. begin
  727.   DecodeDate(value, tmp.year, tmp.month, tmp.day);
  728.   DecodeTime(value, tmp.hour, tmp.minute, tmp.second, fraction);
  729.   tmp.fraction := fraction;
  730.   SetData(SQL_C_TIMESTAMP, tmp, SizeOf(tmp));
  731. end;
  732.  
  733. procedure TIvParameter.SetNull;
  734. var
  735.   code: Integer;
  736. begin
  737.   FBufferSize := SQL_NULL_DATA;
  738.  
  739.   code := SQLDescribeParam(
  740.     FOwner.Handle,
  741.     Number,
  742.     FSqlType,
  743.     FColDef,
  744.     FScale,
  745.     FNullable);
  746.  
  747.   FOwner.HandleReturn(code);
  748.  
  749.   code := SQLBindParameter(
  750.     FOwner.Handle,
  751.     Number,
  752.     SQL_PARAM_INPUT,
  753.     SQL_C_CHAR,
  754.     FSqlType,
  755.     FColDef,
  756.     FScale,
  757.     nil,
  758.     0,
  759.     FBufferSize);
  760.  
  761.   FOwner.HandleReturn(code);
  762. end;
  763.  
  764.  
  765. { TIvStatement }
  766.  
  767. constructor TIvStatement.Create(connection: TIvConnection);
  768. begin
  769.   inherited Create;
  770.   FConnection := connection;
  771.   SQLAllocStmt(FConnection.Handle, FHandle);
  772.   FParameters := TList.Create;
  773. end;
  774.  
  775. destructor TIvStatement.Destroy;
  776. begin
  777.   ClearParameters;
  778.   FParameters.Free;
  779.   SQLFreeStmt(FHandle, SQL_DROP);
  780.   inherited Destroy;
  781. end;
  782.  
  783. procedure TIvStatement.HandleReturn(code: Integer);
  784. begin
  785.   HandleError(code, IvEnvironment.Handle, FConnection.Handle, FHandle);
  786. end;
  787.  
  788. procedure TIvStatement.ExecuteDirect(const sql: String);
  789. var
  790.   code: Integer;
  791. begin
  792.   code := SQLExecDirect(FHandle, PChar(sql), Length(sql));
  793.   HandleReturn(code);
  794. end;
  795.  
  796. procedure TIvStatement.LoadParameters;
  797. var
  798.   i: Integer;
  799.   code: Smallint;
  800.   count: Smallint;
  801. begin
  802.   ClearParameters;
  803.  
  804.   code := SQLNumParams(FHandle, count);
  805.   HandleReturn(code);
  806.  
  807.   for i := 0 to count - 1 do
  808.     FParameters.Add(TIvParameter.Create(Self, i));
  809. end;
  810.  
  811. procedure TIvStatement.ClearParameters;
  812. var
  813.   i: Integer;
  814. begin
  815.   for i := 0 to ParameterCount - 1 do
  816.     Parameters[i].Free;
  817.  
  818.   FParameters.Clear;
  819. end;
  820.  
  821. function TIvStatement.GetParameterCount: Integer;
  822. begin
  823.   Result := FParameters.Count;
  824. end;
  825.  
  826. function TIvStatement.GetParameters(index: Integer): TIvParameter;
  827. begin
  828.   Result := FParameters[index];
  829. end;
  830.  
  831. procedure TIvStatement.Prepare(const sql: String);
  832. var
  833.   code: Integer;
  834. begin
  835.   code := SQLPrepare(FHandle, PChar(sql), Length(sql));
  836.   HandleReturn(code);
  837.  
  838.   LoadParameters;
  839. end;
  840.  
  841. procedure TIvStatement.InitParameters;
  842. var
  843.   i: Integer;
  844. begin
  845.   for i := 0 to ParameterCount - 1 do
  846.     Parameters[i].SetNull;
  847. end;
  848.  
  849. procedure TIvStatement.Execute;
  850. var
  851.   code: Integer;
  852. begin
  853.   code := SQLExecute(FHandle);
  854.   HandleReturn(code);
  855. end;
  856.  
  857. procedure TIvStatement.Close;
  858. begin
  859.   SQLFreeStmt(FHandle, SQL_CLOSE);
  860. end;
  861.  
  862.  
  863. { TIvColumn }
  864.  
  865. constructor TIvColumn.Create(
  866.   owner: TIvResultSet;
  867.   index: Integer);
  868. var
  869.   code: Integer;
  870.   columnName: array[0..255] of Char;
  871.   columnNameLength: Smallint;
  872. begin
  873.   inherited Create;
  874.   FOwner := owner;
  875.   FIndex := index;
  876.   columnNameLength := 0;
  877.  
  878.   code := SQLDescribeCol(
  879.     FOwner.Handle,
  880.     Number,
  881.     columnName,
  882.     SizeOf(columnName),
  883.     columnNameLength,
  884.     FDataType,
  885.     FSize,
  886.     FDecimalDigits,
  887.     FNullable);
  888.  
  889.   owner.HandleReturn(code);
  890.  
  891.   FName := StrPas(columnName);
  892. end;
  893.  
  894. destructor TIvColumn.Destroy;
  895. begin
  896.   inherited Destroy;
  897. end;
  898.  
  899. function TIvColumn.GetIsBlob: Boolean;
  900. begin
  901.   Result := False;
  902. end;
  903.  
  904. function TIvColumn.GetNumber: Integer;
  905. begin
  906.   Result := FIndex + 1;
  907. end;
  908.  
  909. function TIvColumn.GetData(
  910.   targetType: Smallint;
  911.   var buffer;
  912.   bufferLength: Integer;
  913.   var indicator: Integer): Integer;
  914. begin
  915.   Result := SQLGetData(
  916.     FOwner.Handle,
  917.     Number,
  918.     targetType,
  919.     @buffer,
  920.     bufferLength,
  921.     indicator);
  922.  
  923.   FWasNull := (indicator = SQL_NULL_DATA);
  924.   FOwner.HandleReturn(Result);
  925. end;
  926.  
  927. function TIvColumn.GetAsStream: TMemoryStream;
  928. var
  929.   code: Integer;
  930.   length: Integer;
  931.   numBytes: Integer;
  932.   buffer: array[0..65535] of Byte;
  933. begin
  934.   Result := TMemoryStream.Create;
  935.  
  936.   repeat
  937.     code := GetData(SQL_C_BINARY, buffer, SizeOf(buffer), length);
  938.  
  939.     if length > 0 then
  940.     begin
  941.       if (length > SizeOf(buffer)) or (length = SQL_NO_TOTAL) then
  942.         numBytes := SizeOf(buffer)
  943.       else
  944.         numBytes := length;
  945.  
  946.       Result.Write(buffer, numBytes);
  947.     end;
  948.   until (code = SQL_SUCCESS);
  949.  
  950.   Result.Seek(0, soFromBeginning);
  951. end;
  952.  
  953. function TIvColumn.GetAsBoolean: Boolean;
  954. var
  955.   length: Integer;
  956. begin
  957.   GetData(SQL_C_BIT, Result, SizeOf(Result), length);
  958. end;
  959.  
  960. function TIvColumn.GetAsDate: TDateTime;
  961. var
  962.   length: Integer;
  963.   tmp: TOdbcDateStruct;
  964. begin
  965.   GetData(SQL_C_DATE, tmp, SizeOf(tmp), length);
  966.   Result := EncodeDate(tmp.year, tmp.month, tmp.day);
  967. end;
  968.  
  969. function TIvColumn.GetAsCurrency: Currency;
  970. var
  971.   length: Integer;
  972.   tmp: Double;
  973. begin
  974.   GetData(SQL_C_DOUBLE, tmp, SizeOf(Result), length);
  975.   Result := tmp;
  976. end;
  977.  
  978. function TIvColumn.GetAsFloat: Double;
  979. var
  980.   length: Integer;
  981. begin
  982.   GetData(SQL_C_DOUBLE, Result, SizeOf(Result), length);
  983. end;
  984.  
  985. function TIvColumn.GetAsInteger: Integer;
  986. var
  987.   length: Integer;
  988. begin
  989.   GetData(SQL_C_SLONG, Result, SizeOf(Result), length);
  990. end;
  991.  
  992. function TIvColumn.GetAsString: String;
  993. var
  994.   code: Integer;
  995.   length: Integer;
  996.   buffer: array[0..255] of Char;
  997. begin
  998.   Result := '';
  999.  
  1000.   repeat
  1001.     code := GetData(SQL_C_CHAR, buffer, SizeOf(buffer), length);
  1002.  
  1003.     if length > 0 then
  1004.       Result := Result + StrPas(buffer);
  1005.   until (code = SQL_SUCCESS)
  1006. end;
  1007.  
  1008. function TIvColumn.GetAsTime: TDateTime;
  1009. var
  1010.   len: Integer;
  1011.   tmp: TOdbcTimeStruct;
  1012. begin
  1013.   GetData(SQL_C_TIME, tmp, SizeOf(tmp), len);
  1014.   Result := EncodeTime(tmp.hour, tmp.minute, tmp.second, 0);
  1015. end;
  1016.  
  1017. function TIvColumn.GetAsDateTime: TDateTime;
  1018. var
  1019.   len: Integer;
  1020.   tmp: TOdbcTimestampStruct;
  1021. begin
  1022.   GetData(SQL_C_TIMESTAMP, tmp, SizeOf(tmp), len);
  1023.  
  1024.   Result := EncodeDate(tmp.year, tmp.month, tmp.day) +
  1025.     EncodeTime(tmp.hour, tmp.minute, tmp.second, 0);
  1026. end;
  1027.  
  1028.  
  1029. { TIvResultSet }
  1030.  
  1031. constructor TIvResultSet.Create(connection: TIvConnection);
  1032. begin
  1033.   inherited Create(connection);
  1034.   FColumns := TList.Create;
  1035. end;
  1036.  
  1037. destructor TIvResultSet.Destroy;
  1038. begin
  1039.   ClearColumns;
  1040.   FColumns.Free;
  1041.   inherited Destroy;
  1042. end;
  1043.  
  1044. function TIvResultSet.GetColumnCount: Integer;
  1045. begin
  1046.   Result := FColumns.Count;
  1047. end;
  1048.  
  1049. function TIvResultSet.GetColumns(index: Integer): TIvColumn;
  1050. begin
  1051.   Result := FColumns[index];
  1052. end;
  1053.  
  1054. function TIvResultSet.ColumnByName(const name: String): TIvColumn;
  1055. var
  1056.   i: Integer;
  1057. begin
  1058.   for i := 0 to ColumnCount - 1 do
  1059.   begin
  1060.     Result := Columns[i];
  1061.  
  1062.     if LowerCase(Result.Name) = LowerCase(name) then
  1063.       Exit;
  1064.   end;
  1065.  
  1066.   raise Exception.Create(Format('Column %s not found', [name]));
  1067. end;
  1068.  
  1069. procedure TIvResultSet.LoadColumns;
  1070. var
  1071.   count: Smallint;
  1072.   code: Integer;
  1073.   i: Integer;
  1074. begin
  1075.   ClearColumns;
  1076.   code := SQLNumResultCols(FHandle, count);
  1077.   HandleReturn(code);
  1078.  
  1079.   for i := 0 to count - 1 do
  1080.     FColumns.Add(TIvColumn.Create(Self, i));
  1081. end;
  1082.  
  1083. procedure TIvResultSet.ClearColumns;
  1084. var
  1085.   i: Integer;
  1086. begin
  1087.   for i := 0 to ColumnCount - 1 do
  1088.     Columns[i].Free;
  1089.  
  1090.   FColumns.Clear;
  1091. end;
  1092.  
  1093. procedure TIvResultSet.ExecuteDirect(const sql: String);
  1094. begin
  1095.   inherited ExecuteDirect(sql);
  1096.   LoadColumns;
  1097. end;
  1098.  
  1099. procedure TIvResultSet.ExecuteDirectFast(const sql: String);
  1100. begin
  1101.   inherited ExecuteDirect(sql);
  1102. end;
  1103.  
  1104. procedure TIvResultSet.Prepare(const sql: String);
  1105. begin
  1106.   inherited Prepare(sql);
  1107. end;
  1108.  
  1109. procedure TIvResultSet.Execute;
  1110. begin
  1111.   inherited Execute;
  1112.   LoadColumns;
  1113. end;
  1114.  
  1115. function TIvResultSet.Next: Boolean;
  1116. var
  1117.   code: Integer;
  1118. begin
  1119.   code := SQLFetch(FHandle);
  1120.  
  1121.   if code <> SQL_NO_DATA then
  1122.     HandleReturn(code);
  1123.  
  1124.   Result := (code <> SQL_NO_DATA);
  1125.   FEOF := not Result;
  1126. end;
  1127.  
  1128.  
  1129. initialization
  1130. {$IFDEF IVSTATICODBC}
  1131.   IvEnvironment := TIvEnvironment.Create;
  1132. {$ELSE}
  1133.   IvEnvironment := nil;
  1134.   if IsODBCAvailable then
  1135.     IvEnvironment := TIvEnvironment.Create;
  1136. {$ENDIF}
  1137. finalization
  1138.   IvEnvironment.Free;
  1139. end.
  1140.